﻿namespace MicroCloud.Extensions
{
    #region "<see cref="IEnumerable{T}"/> 扩展操作类"
    /// <summary>
    /// <see cref="IEnumerable{T}"/> 扩展操作类
    /// </summary>
    public static class EnumerableExtensions
    {
        ///// <summary>
        ///// 将 <see cref="IEnumerable{T}"/> 集合按指定字段与排序方式进行排序
        ///// </summary>
        ///// <typeparam name="T">集合项类型</typeparam>
        ///// <param name="source">要排序的数据集</param>
        ///// <param name="propertyName">排序属性名</param>
        ///// <param name="sortDirection">排序方向</param>
        ///// <returns>排序后的数据集</returns>
        //public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> source,
        //    string propertyName,
        //    ListSortDirection sortDirection = ListSortDirection.Ascending)
        //{
        //    propertyName.CheckNotNullOrEmpty(nameof(propertyName));
        //    return CollectionPropertySorter<T>.OrderBy(source, propertyName, sortDirection);
        //}


        ///// <summary>
        ///// 将 <see cref="IEnumerable{T}"/> 集合按指定字段排序条件进行排序
        ///// </summary>
        ///// <typeparam name="T">动态类型</typeparam>
        ///// <param name="source">要排序的数据集</param>
        ///// <param name="sortCondition">列表字段排序条件</param>
        ///// <returns></returns>
        //public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> source, SortCondition sortCondition)
        //{
        //    sortCondition.CheckNotNull(nameof(sortCondition));
        //    return source.OrderBy(sortCondition.SortField, sortCondition.ListSortDirection);
        //}

        ///// <summary>
        ///// 将 <see cref="IEnumerable{T}"/> 集合按指定字段排序条件进行排序
        ///// </summary>
        ///// <typeparam name="T">动态类型</typeparam>
        ///// <param name="source">要排序的数据集</param>
        ///// <param name="sortCondition">列表字段排序条件</param>
        ///// <returns></returns>
        //public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> source, SortCondition<T> sortCondition)
        //{
        //    sortCondition.CheckNotNull(nameof(sortCondition));
        //    return source.OrderBy(sortCondition.SortField, sortCondition.ListSortDirection);
        //}

        #region "方法"
        #region "从指定 <see cref="IEnumerable{T}"/ >集合中查询未过期的子数据集，用于筛选实现了 <see cref="IExpirable"/> 接口的数据集"
        /// <summary>
        /// 从指定 <see cref="IEnumerable{T}"/> 集合中查询未过期的子数据集，用于筛选实现了 <see cref="IExpirable"/> 接口的数据集
        /// </summary>
        public static IEnumerable<TEntity> Unexpired<TEntity>(this IEnumerable<TEntity> source)
            where TEntity : class, IExpirable
        {
            DateTime now = DateTime.Now;
            bool Func(TEntity m) => (m.BeginTime == null || m.BeginTime.Value <= now) && (m.EndTime == null || m.EndTime.Value >= now);
            return source.Where(Func);
        }
        #endregion
        #region "从指定 <see cref="IEnumerable{T}"/> 集合中查询已过期的子数据集，用于筛选实现了 <see cref="IExpirable"/> 接口的数据集"
        /// <summary>
        /// 从指定 <see cref="IEnumerable{T}"/> 集合中查询已过期的子数据集，用于筛选实现了 <see cref="IExpirable"/> 接口的数据集
        /// </summary>
        public static IEnumerable<TEntity> Expired<TEntity>(this IEnumerable<TEntity> source)
            where TEntity : class, IExpirable
        {
            DateTime now = DateTime.Now;
            bool Func(TEntity m) => m.EndTime != null && m.EndTime.Value < now;
            return source.Where(Func);
        }
        #endregion
        #region "从指定 <see cref="IEnumerable{T}"/> 数据集中查询未锁定的子数据集，用于筛选实现了 <see cref="ILockable"/> 接口的数据集"
        /// <summary>
        /// 从指定 <see cref="IEnumerable{T}"/> 数据集中查询未锁定的子数据集，用于筛选实现了 <see cref="ILockable"/> 接口的数据集
        /// </summary>
        public static IEnumerable<TEntity> Unlocked<TEntity>(this IEnumerable<TEntity> source)
            where TEntity : class, ILockable
        {
            return source.Where(m => !m.IsLocked);
        }
        #endregion
        #region "从指定 <see cref="IEnumerable{T}"/> 数据集中查询已锁定的子数据集，用于筛选实现了 <see cref="ILockable"/> 接口的数据集"
        /// <summary>
        /// 从指定 <see cref="IEnumerable{T}"/> 数据集中查询已锁定的子数据集，用于筛选实现了 <see cref="ILockable"/> 接口的数据集
        /// </summary>
        public static IEnumerable<TEntity> Locked<TEntity>(this IEnumerable<TEntity> source)
            where TEntity : class, ILockable
        {
            return source.Where(m => m.IsLocked);
        }
        #endregion

        #region "检查指定实体的Hash值，决定是否需要进行数据库同步"
        /// <summary>
        /// 检查指定实体的Hash值，决定是否需要进行数据库同步
        /// </summary>
        /// <param name="entityHashes">实体Hash集合</param>
        /// <param name="provider">服务提供者</param>
        /// <param name="logger">日志对象</param>
        /// <param name="entityType">实体类型</param>
        /// <param name="handlerType">处理器类型，默认实体类型</param>
        /// <param name="display">显示名称</param>
        /// <param name="remark">备注</param>
        /// <returns>同步返回true，不同步返回false</returns>
        public static bool CheckSyncByHash(this IEnumerable<IEntityHash> entityHashes, IServiceProvider provider, ILogger logger
            , Type entityType = null, Type handlerType = null, string display = null, string remark = null)
        {
            IEntityHash[] hashes = entityHashes as IEntityHash[] ?? entityHashes.ToArray();
            if (hashes.Length == 0)
            {
                return false;
            }
            entityType ??= entityHashes.FirstOrDefault()?.GetType();
            handlerType ??= entityType;
            string hash = hashes.Select(m => m.GetHash(entityType)).ExpandAndToString().ToMD5();
            string key = $"Hash.SyncToDatabase-{handlerType.GetFullNameWithModule()}";

            var store = provider.GetService<IKeyValueStore>();
            var dictionary = store.GetByKey(key);
            if (dictionary != null && dictionary.Value?.ToString() == hash)
            {
                logger.LogDebug("{length} 条 {entityType} 的数据内容签名 {hash} 与上次相同，跳过数据库同步。", hashes.Length, entityType, hash);
                return false;
            }

            display ??= entityType?.GetDescription();
            store.CreateOrUpdate(key, hash, display, remark).GetAwaiter().GetResult();
            logger.LogDebug("{length} 条 {entityType} 的数据内容签名 {hash} 与上次 {value} 不同，执行数据库同步。", hashes.Length, entityType, hash, dictionary?.Value);
            return true;
        }
        #endregion

        #endregion

    }
    #endregion

}
